package com.yuandian.utils;

import com.yuandian.api.business_monitor.vo.UserActionBusiStepListVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.cglib.core.Converter;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * <p>
 * Bean工具类
 * 使用BeanCopier
 * </p>
 *
 * @author: tangqingchun
 * @date: 2020-07-09
 */
@Slf4j
public class BeanUtils {

	private static Object obj;

	/**
     * 禁止实例化
     */
    private BeanUtils() {}

    /**
     * 使用缓存提高效率
     **/
    private static final Map<String, BeanCopier> BEAN_COPIER_MAP = new ConcurrentHashMap<>();


	/**
	 * List类型转换
	 * <p>
	 * 浅复制，字段名&类型相同则被复制
	 * </p>
	 *
	 * @param source 源对象
	 * @param targetClass 待转换的class对象
	 * @return
	 */
	public static <E> List<E> convert(List source, Class<E> targetClass){
		return convert(source, targetClass, null);
	}

	/**
	 * List类型转换-自定义转换器
	 * <p>
	 * 浅复制，字段名&类型相同则被复制
	 * </p>
	 *
	 * @param source 源对象
	 * @param targetClass 待转换的class对象
	 * @return
	 */
	public static <E> List<E> convert(List source, Class<E> targetClass, Converter converter){
		if (source == null) {
			return null;
		}
		if (source.isEmpty()) {
			return new ArrayList<>();
		}
		List<E> result = new ArrayList<>(source.size());

		for (Object each : source) {
			result.add(convert(each, targetClass, converter));
		}
		return result;
	}

	/**
	 * Bean对象转换
	 * <p>
	 * 浅复制，字段名&类型相同则被复制
	 * </p>
	 *
	 * @param source 源对象
	 * @param targetClass 目标Class对象
	 * @return T
	 */
	public static <T> T convert(Object source, Class<T> targetClass) {
		return convert(source, targetClass, null);
	}

	/**
	 * Bean对象转换-自定义转换器
	 * <p>
	 * 浅复制，字段名&类型相同则被复制
	 * </p>
	 *
	 * @param source 源对象
	 * @param targetClass 目标Class对象
	 * @param converter 自定义转换器
	 * @return T
	 */
	public static <T> T convert(Object source, Class<T> targetClass, Converter converter) {
		if (source == null) {
			return null;
		}
		BeanCopier beanCopier = getBeanCopier(source, targetClass, converter);
		try {
			T target = targetClass.newInstance();
			beanCopier.copy(source, target, converter);
			return target;
		} catch (Exception e) {
			log.error("对象拷贝失败,source:{}, targetClass:{}, Exception{}", source, targetClass, e);
			throw new RuntimeException("对象拷贝失败");
		}
	}


	/**
	 * 获取beanCopier
	 *
	 * @param source 源目标
	 * @param targetClass 目标class对象
	 * @param converter 转换器
	 * @return
	 */
	private static <T> BeanCopier getBeanCopier(Object source, Class<T> targetClass, Converter converter){
		boolean useConverter = false;
		if (converter != null){
			useConverter = true;
		}
		String beanKey = generateKey(source.getClass(), targetClass);
		BeanCopier beanCopier = BEAN_COPIER_MAP.get(beanKey);
		if (beanCopier == null) {
			beanCopier = BeanCopier.create(source.getClass(), targetClass, useConverter);
			BEAN_COPIER_MAP.put(beanKey, beanCopier);
		}
		return beanCopier;
	}

    /**
     * 类型强转
     * @param obj
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T cast(Object obj) {
        return (T) obj;
    }

    /**
     * MAP_CACHES的KEY生成
     *
     * @param source 源class对象
     * @param target 目标class对象
     * @return
     */
    private static String generateKey(Class<?> source, Class<?> target) {
        return source.toString() + target.toString();
    }


	/**
	 * map转object
	 * @param map 待转换map
	 * @param clazz 目标class
	 * @param ignoreList 忽略转换的字段
	 * @param <T> 泛型
	 * @return 对象
	 */
	public static <T> T mapToObject(Map<String, Object> map, Class<T> clazz, List<String> ignoreList) {
		if (map == null) {
			return null;
		}
		try {
			T object = clazz.newInstance();
			BeanMap beanMap = BeanMap.create(object);
			if (ignoreList == null) {
				beanMap.putAll(map);
			} else {
				map.forEach((k, v) -> {
					if (!ignoreList.contains(k)) {
						Class<?> propertyClazz = beanMap.getPropertyType(k);
						if (propertyClazz != null && v != null) {
							String propertyType = propertyClazz.getName();
							String valType = v.getClass().getName();
							if ("java.lang.Long".equals(propertyType) && "java.lang.Integer".equals(valType)) {
								v = ((Integer) v).longValue();
							} else if ("java.util.Date".equals(propertyType) && "java.lang.String".equals(valType)) {
								v = YDateUtil.yyyy_MM_dd_HH_mm_ss(String.valueOf(v));
							} else if ("java.lang.Float".equals(propertyType) && "java.lang.Integer".equals(valType)) {
								v = Float.valueOf(((Integer) v).toString());
							} else if ("java.lang.String".equals(propertyType) && "java.lang.Integer".equals(valType)) {
								v = ((Integer) v).toString();
							}else if ("java.lang.String".equals(propertyType) && "java.lang.Long".equals(valType)) {
								v = ((Long) v).toString();
							}
						}
						beanMap.put(k, v);
					}
				});
			}
			return object;
		} catch (Exception e) {
			log.error("对象拷贝失败,clazz:{}, Exception{}", clazz, e);
			throw new RuntimeException("对象拷贝失败!");
		}
	}

    /**
     * 获取beanCopier
     *
     * @param source 源目标
     * @param targetClass 目标class对象
     * @param converter 转换器
     * @return
     */
//    private static <T> BeanCopier getBeanCopier(Object source, Class<T> targetClass, Converter converter){
//        boolean useConverter = false;
//        if (converter != null){
//            useConverter = true;
//        }
//        String beanKey = generateKey(source.getClass(), targetClass);
//        BeanCopier beanCopier = BEAN_COPIER_MAP.get(beanKey);
//        if (beanCopier == null) {
//            beanCopier = BeanCopier.create(source.getClass(), targetClass, useConverter);
//            BEAN_COPIER_MAP.put(beanKey, beanCopier);
//        }
//        return beanCopier;
//    }
}
